package com.yzq.os.spider.v.controller;

import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.yzq.os.spider.v.Constants;
import com.yzq.os.spider.v.domain.Record;
import com.yzq.os.spider.v.domain.SearchEngine;
import com.yzq.os.spider.v.domain.Server;
import com.yzq.os.spider.v.service.CrawlService;
import com.yzq.os.spider.v.service.domain.QueryURLService;
import com.yzq.os.spider.v.service.domain.SearchEngineService;
import com.yzq.os.spider.v.service.domain.ServerService;
import com.yzq.os.spider.v.service.domain.SpiderRecordService;

/**
 * 抓取统计控制器
 * 
 * @author 苑志强(xingyu_yzq@163.com)
 * 
 */
@Controller
@RequestMapping("/statis")
public class ProcStatisticsController {

	private static Logger logger = Logger
			.getLogger(ProcStatisticsController.class);

	/**
	 * 应用获取抓取统计数据的接口地址
	 */
	private static String LOAD_SERVER_SPEED_URL = "http://<SERVER_IP_ADDRESS>:8080/<CONTEXT_PATH>/admin/statis/loadLocalSpeed";

	/**
	 * 服务器没有运行的提示数据
	 */
	private static String NOT_RUNNING = "Not Runing";

	@Autowired
	private QueryURLService queryURLService;

	@Autowired
	private SpiderRecordService crawlJobService;

	@Autowired
	private SearchEngineService searchEngineService;

	@Autowired
	private ServerService serverService;

	/**
	 * 获取搜索URL的抓取统计信息（已经执行的多少搜索URL提交，及状态都是怎样）
	 * 
	 * @return
	 */
	@RequestMapping("/queryurl")
	@ResponseBody
	public List<String[]> queryUrl() {
		List<String[]> result = new ArrayList<String[]>();
		List<SearchEngine> engines = searchEngineService.findAllList();
		if (CollectionUtils.isNotEmpty(engines)) {
			for (SearchEngine engine : engines) {
				List<String[]> statis = queryURLService.procStatistics(engine
						.getId());
				if (CollectionUtils.isNotEmpty(statis)) {
					result.addAll(statis);
				}
			}
		}
		return result;
	}

	/**
	 * 获取完成进度条数值（进度条显示百分比）
	 * 
	 * @return
	 */
	@RequestMapping("/progressbar")
	@ResponseBody
	public List<String[]> progressbar() {
		List<String[]> result = new ArrayList<String[]>();
		List<SearchEngine> engines = searchEngineService.findAllList();
		if (CollectionUtils.isNotEmpty(engines)) {
			for (SearchEngine engine : engines) {
				result.addAll(queryURLService.progressbar(engine.getId()));
			}
		}
		return result;
	}

	/**
	 * 获取抓取数据的统计信息（已经抓取到了多少记录）
	 * 
	 * @return
	 * @throws ParseException
	 */
	@RequestMapping("/spiderRecord")
	@ResponseBody
	public List<String[]> spiderRecord() throws ParseException {
		List<String[]> infos = new ArrayList<String[]>();
		List<SearchEngine> engines = searchEngineService.findAllList();
		if (CollectionUtils.isNotEmpty(engines)) {
			for (SearchEngine engine : engines) {
				int engineId = engine.getId();
				String tableName = crawlJobService.findLastExistTable(engineId);
				if (StringUtils.isNotBlank(tableName)) {
					String[] statis = crawlJobService.crawledStatistics(
							engineId, tableName);
					if (statis != null) {
						infos.add(statis);
					} else {
						// have table but not record
						String[] info = new String[4];
						info[0] = String.valueOf(engineId);
						info[1] = String.valueOf(Record.DO_FLAG);
						info[2] = "0";
						info[3] = tableName;
						infos.add(info);
					}
				} else {
					// not have table
					String[] info = new String[4];
					info[0] = String.valueOf(engineId);
					info[1] = String.valueOf(Record.DO_FLAG);
					info[2] = "-1";
					info[3] = "Still no tables";
					infos.add(info);
				}
			}
		}
		return infos;
	}

	/**
	 * 获取集群抓取的统计信息
	 * 
	 * @return
	 */
	@RequestMapping()
	public ModelAndView statis() {
		Map<String, Object> model = new TreeMap<String, Object>();
		List<SearchEngine> engines = searchEngineService.findAllList();
		List<String> items = new ArrayList<String>();
		for (SearchEngine engine : engines) {
			items.add("\"" + engine.getId() + "\":\"" + engine.getName() + "\"");
		}
		model.put("engines", "{" + StringUtils.join(items, ",") + "}");
		return new ModelAndView("/admin/statis/load", model);
	}

	/**
	 * 获取集群执行速度方面的统计信息（每秒提交多少URL，每秒抓取到多少列表记录）
	 * 
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("/loadSpeed")
	@ResponseBody
	public Map<String, List<String[]>> loadSpeed() throws IOException {
		Map<String, List<String[]>> result = new TreeMap<String, List<String[]>>();
		List<Server> servers = serverService.findAll();
		for (Server server : servers) {
			String ip = server.getIp();
			try {
				result.put(ip, loadServerSpeed(ip));
			} catch (Exception e) {
				logger.error("ip:[" + ip + "]", e);
			}
		}
		return result;
	}

	/**
	 * 获取本机的抓取速度统计信息
	 * 
	 * @return
	 * @throws ClassNotFoundException
	 */
	@RequestMapping("/loadLocalSpeed")
	@ResponseBody
	public List<String[]> loadLocalSpeed() throws ClassNotFoundException {
		List<String[]> returnList = new ArrayList<String[]>();
		List<Integer> engineIds = CrawlService.getRunningEngineId();
		if (CollectionUtils.isNotEmpty(engineIds)) {
			for (Integer engineId : engineIds) {
				Date taskStartDate = CrawlService.takeStartDate(engineId);
				int crawQueryUrlCount = CrawlService.takeQueryCount(engineId);
				String crawlQueryUrlSpeed = CrawlService
						.takeQuerySpeed(engineId) + "/second";
				int crawlJobsCount = CrawlService.takeJobCount(engineId);
				String crawlJobSpeed = CrawlService.takeJobSpeed(engineId)
						+ "/second";
				boolean haveRunning = SpiderRecordService
						.haveRunningThreadAndRunnable(engineId);
				String[] strs1 = new String[8];
				strs1[0] = String.valueOf(engineId);
				strs1[1] = taskStartDate != null ? DateFormatUtils.format(
						taskStartDate, Constants.DATE_WITH_TIME_PATTERN)
						: NOT_RUNNING;
				strs1[2] = DateFormatUtils.format(new Date(),
						Constants.DATE_WITH_TIME_PATTERN);
				strs1[3] = String.valueOf(crawQueryUrlCount);
				strs1[4] = crawlQueryUrlSpeed;
				strs1[5] = String.valueOf(crawlJobsCount);
				strs1[6] = crawlJobSpeed;
				strs1[7] = String.valueOf(haveRunning);

				returnList.add(strs1);
			}
		}
		return returnList;
	}

	/**
	 * 获取指定IP地址的抓取速度统计信息
	 * 
	 * @param ip
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	private List<String[]> loadServerSpeed(String ip) throws IOException {
		URL url = new URL(StringUtils.replaceEach(LOAD_SERVER_SPEED_URL,
				new String[] { "<SERVER_IP_ADDRESS>", "<CONTEXT_PATH>" },
				new String[] { ip, serverService.getContextPath() }));
		ObjectMapper map = new ObjectMapper();
		List<String[]> list = map.readValue(url, List.class);
		logger.info("Form ip[" + ip + "],load speed:["
				+ CollectionUtils.size(list) + "]");
		return list;
	}

	/**
	 * 清空指定搜索引擎的抓取速度统计信息
	 * 
	 * @param engineId
	 * @return
	 * @throws ClassNotFoundException
	 */
	@RequestMapping("/clearSpeed/{engineId}")
	@ResponseBody
	public String clearSpeed(@PathVariable int engineId)
			throws ClassNotFoundException {
		logger.info("Clear speed engineId:[" + engineId + "]");
		CrawlService.resetSpeedStatis(engineId, new Date(),
				new AtomicInteger(0), new AtomicInteger(0));
		return "OK";
	}

}
